﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using DownLoadHttp;
using xmlclass;
using System.Threading;
using System.IO;
using System.Diagnostics;

namespace autoupdater
{
    public partial class mianform : Form
    {

        public class NodeInfo
        {
            public string filename { get; set; }
            public int version { get; set; }
            public string path { get; set; }
            public long fsize { get; set; }
        }

        public HttpDownLoad httpdown;
        public XMLoperationClass xoc;
        public List<NodeInfo> fls = null;//本地文件列表
        public List<NodeInfo> fl = null;//远程文件列表
        public List<NodeInfo> ufl = null;//可以升级文件列表
        public string upurl;
        private string runfilename;
        public mianform()
        {
            InitializeComponent();
        }

        private void onProcess(int val, string msg)
        {
            progressBar1.Invoke(new Action(() =>
            {
                progressBar1.Value = val;
                label2.Text = msg;
            }));
        }

        private void LoadConfig()
        {
            XMLoperationClass xc = new XMLoperationClass();
            xc.filename = "config.xml";
            if (!File.Exists("config.xml"))
            {
                xc.CreateRootNode("config", true);
                xc.CreateNodeValue("Run", "filename", "NattoCarControl.exe", true, false);
                xc.CreateNodeValue("RunState", "Error", "NULL", true, false);
                runfilename = "NattoCarControl.exe";
            }
            else
            {
                xc.GetRoot();
                runfilename = xc.GetAttributeValue("Run", "filename");
            }
        }

        private void SetRunFlag(string msg)
        {
            XMLoperationClass xc = new XMLoperationClass("config.xml");
            xc.SetAttribute("RunState", "RunState", "Error", DateTime.Now.ToString() + " Run " + runfilename + " , " + msg);
        }

        private void mianform_Load(object sender, EventArgs e)
        {
            LoadConfig();
            httpdown = new HttpDownLoad();
            httpdown.onpr = onProcess;
            if (Directory.Exists(Environment.CurrentDirectory + "\\tmp"))
            {
                DeleteDir(new DirectoryInfo(Environment.CurrentDirectory + "\\tmp"));
            }
            LoadUpdateFile();
        }

        private void LoadUpdateFile()
        {
            bool isForceUpdate;
            int TryCount = 0;
            string b1 = "false";
            List<string> rl = null;
            xoc = new XMLoperationClass("fileversion.xml");//本地文件版本信息
            upurl = xoc.GetAttributeValue("updateurl", "url");
            while (!httpdown.downOK)
            {
                httpdown.httpDownFile(upurl + "/up.xml", Environment.CurrentDirectory + "\\up.xml");//更新升级文件列表
                if (httpdown.downOK)
                {
                    XMLoperationClass xo = new XMLoperationClass("up.xml");//远程文件版本信息
                    b1 = xo.GetAttributeValue("upflag", "isforce");
                    rl = xo.GetAttributeValues("file");//获取远程文件例表
                }
                else
                {
                    TryCount++;
                    if (TryCount > 2) break;
                }
            }
            try
            {
                isForceUpdate = Convert.ToBoolean(b1);
            }
            catch
            {
                isForceUpdate = false;
            }

            List<string> ls = xoc.GetAttributeValues("file");//获取本地文件列表
            if (rl != null)
            {
                fl = new List<NodeInfo>();
                for (int i = 0; i < rl.Count; i++)
                {
                    NodeInfo ni = new NodeInfo();
                    string[] p1 = rl[i].Split('|');
                    if (p1.Length > 3)
                    {
                        ni.filename = p1[0].Substring(p1[0].IndexOf('=') + 1);
                        ni.version = Convert.ToInt32(p1[1].Substring(p1[1].IndexOf('=') + 1));
                        ni.fsize = Convert.ToInt64(p1[2].Substring(p1[2].IndexOf('=') + 1));
                        ni.path = p1[3].Substring(p1[3].IndexOf('=') + 1);
                        fl.Add(ni);
                    }
                }
            }
            if (isForceUpdate)
            {
                ufl = new List<NodeInfo>();
                fl.ForEach(i => ufl.Add(i));
                fl.Clear();
            }
            else
            {
                if (ls != null)
                {
                    fls = new List<NodeInfo>();
                    for (int i = 0; i < ls.Count; i++)
                    {
                        NodeInfo ni = new NodeInfo();
                        string[] p1 = ls[i].Split('|');
                        if (p1.Length > 3)
                        {
                            ni.filename = p1[0].Substring(p1[0].IndexOf('=') + 1);
                            ni.version = Convert.ToInt32(p1[1].Substring(p1[1].IndexOf('=') + 1));
                            ni.fsize = Convert.ToInt64(p1[2].Substring(p1[2].IndexOf('=') + 1));
                            ni.path = p1[3].Substring(p1[3].IndexOf('=') + 1);
                            fls.Add(ni);
                        }
                    }
                }
                if ((fls != null) && (fl != null))
                {
                    ufl = new List<NodeInfo>();
                    int ver = -1;
                    for (int i = 0; i < fl.Count; i++)
                    {
                        ver = GetFileVersion(fl[i].filename);
                        if (fl[i].version > ver)
                        {
                            ufl.Add(fl[i]);
                        }
                    }
                    fls.Clear();
                    fl.Clear();
                }
            }
            Thread thr = new Thread(DownloadFile);
            thr.IsBackground = true;//后台线程
            thr.Start();
        }

        private int GetFileVersion(string filename)
        {
            for (int i = 0; i < fls.Count; i++)
            {
                if (fls[i].filename == filename)
                {
                    return fls[i].version;
                }
            }
            return -1;
        }

        private void DownloadFile()
        {
            NodeInfo di;
            int idx = 0;
            int retry = 0;
            if ((ufl != null) && (ufl.Count > 0))
            {
                for (int i = 0; i < ufl.Count; i++)
                {
                    di = ufl[i];
                    string ul = upurl + di.path.Replace('\\', '/') + di.filename;
                    httpdown.isCover = true;
                    retry = 0;
                    while (retry < 5)
                    {
                        httpdown.httpDownFile(ul, Environment.CurrentDirectory + "\\tmp\\" + di.path + "\\" + di.filename);
                        if (httpdown.downOK)
                        {
                            idx++;
                            break;
                        }
                        else
                        {
                            retry++;
                            Thread.Sleep(2000);//等2秒后再重试
                        }
                    }
                    label1.Invoke(new Action(() =>
                    {
                        label1.Text = "Current " + idx + " -- " + ufl.Count + "     filename:  " + di.filename;
                    }));
                }
                if (idx < ufl.Count)
                {
                    label2.Invoke(new Action(() =>
                    {
                        label2.Text = "download fail!";
                        label2.ForeColor = System.Drawing.Color.Red;
                    }));
                }
                else if (idx == ufl.Count)
                {
                    AddLog("File download completed, ready to update the program ");
                    for (int i = 0; i < ufl.Count; i++)
                    {
                        di = ufl[i];
                        di.path = di.path.Replace('/', '\\');
                        string s1 = Environment.CurrentDirectory + "\\tmp" + di.path + "\\" + di.filename;
                        string s2 = Environment.CurrentDirectory + "\\" + di.path;
                        if (!Directory.Exists(s2))
                        {
                            Directory.CreateDirectory(s2);
                        }
                        s2 += "\\" + di.filename;
                        try
                        {
                            AddLog("update " + di.filename);
                            File.Copy(s1, s2, true);
                        }
                        catch (IOException e)
                        {
                            ;
                        }
                    }
                }
            }
            if (Directory.Exists(Environment.CurrentDirectory + "\\tmp"))
            {
                DeleteDir(new DirectoryInfo(Environment.CurrentDirectory + "\\tmp"));
            }
            RunMainExe();
            Application.Exit();
        }

        private void AddLog(string msg)
        {
            label1.Invoke(new Action(() =>
            {
                label1.Text = msg;
            }));
        }

        private void DeleteDir(DirectoryInfo di)
        {
            DirectoryInfo[] dd = di.GetDirectories();
            if (dd.Length > 0)
            {
                foreach (DirectoryInfo d in dd)
                {
                    DeleteDir(d);
                }

            }
            FileInfo[] ff = di.GetFiles();
            for (int i = 0; i < ff.Length; i++)
            {
                ff[i].Delete();
            }
            di.Delete();
        }
        private void RunMainExe()
        {
            try
            {
                if (File.Exists("up.xml"))
                {
                    File.Delete("up.xml");//删除升级文件列表
                }
            }
            catch
            {
                ;
            }
            try
            {
                //启动主程序
                Process pc = Process.Start(Environment.CurrentDirectory + "/" + runfilename);
            }
            catch (Exception e)
            {
                SetRunFlag(e.Message);
            }
        }

        private void mianform_FormClosed(object sender, FormClosedEventArgs e)
        {
            httpdown.stopDown = true;
            Thread.Sleep(200);
        }
    }
}
